package imageexample;


import java.io.*;
import java.util.TreeSet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import imageexample.ShowImage;

public class Image extends Component implements ActionListener,MouseListener{


    
    
    private int type; 
    private BufferedImage bi,colorimage;
    private int[] histograma = new int[255];
    private int[] intervalo=new int[3];
    
    JFrame frame = new JFrame("Display image");
    
    JTextField r0 = new JTextField("5");
    JTextField r1 = new JTextField("100");
    JTextField r2 = new JTextField("200");
    JTextField g0 = new JTextField("100");
    JTextField g1 = new JTextField("10");
    JTextField g2 = new JTextField("160");
    JTextField b0 = new JTextField("60");
    JTextField b1 = new JTextField("20");
    JTextField b2 = new JTextField("220");
    
    JTextField f0 = new JTextField("0");
    JTextField f1 = new JTextField("1");
    JTextField f2 = new JTextField("0");
    JTextField f3 = new JTextField("1");
    JTextField f4 = new JTextField("-5");
    JTextField f5 = new JTextField("1");
    JTextField f6 = new JTextField("0");
    JTextField f7 = new JTextField("1");
    JTextField f8 = new JTextField("0");
    JTextField z0 = new JTextField("100");
    JTextField z1 = new JTextField("100");
    
    JLabel lblIntervalos = new JLabel("intervalos");
    JLabel lblFiltros = new JLabel("Filtros");
    JLabel lblZoom = new JLabel("Zoom");
    
    
    JButton reg = new JButton("Registración");
    JButton comp = new JButton("Componer_por_otsu");
    JButton compo = new JButton("componer");
    JButton b = new JButton("Gris-Color");
    JButton f = new JButton("Filtro");
    JButton prewitt = new JButton("prewitt"); 
    JButton c = new JButton("Binarizar");
    JButton to = new JButton("Color-gris");
    JButton ci = new JButton("Cargar Imágen");
    JButton zo = new JButton("Escalar");
    JButton ctrt = new JButton("Aplicar Contraste");
    JButton pc = new JButton("cargar_imagenes_registrar_madre");
    JButton pch = new JButton("cargar_imagenes_registrar_hijas");
    JButton ri = new JButton("RegistrarImagenes");
    JButton gpc = new JButton("Cargar Puntos Control");
    JButton gmc = new JButton("Generar Mascara Composicion");
    
            //agrege
    ShowImage img = new ShowImage("C:/Users/rodrigo/Desktop/sangre.jpg");
    ShowImage img2 = new ShowImage("C:/Users/rodrigo/Desktop/sangre.jpg");
    ShowImage[] vectordeimagenes;
    

    
    
    
    int w, h;
    
   
    public Image() {
        int pixelgris;
        try {
            bi = ImageIO.read(new File("C:/Users/rodrigo/Desktop/sangre.jpg"));
            w = bi.getWidth(null);
            h = bi.getHeight(null);
            Graphics big = bi.getGraphics();
            big.drawImage(bi, 0, 0, null);
            this.type=bi.getType();
            
           
            
            this.intervalo[0]=0x05643C;
            this.intervalo[1]=0x640A14;
            this.intervalo[2]=0xC8A0DC;
                    
        } catch (IOException e) {
            System.out.println("Image could not be read");
            System.exit(1);
        }
    }
    
    public void setShowImages() throws IOException
    {
          JFileChooser selector=new JFileChooser();
          FileNameExtensionFilter filtroImagen=new FileNameExtensionFilter("JPG, PNG & GIF","jpg","png","gif");
          selector.setFileFilter(filtroImagen);
          int r=selector.showOpenDialog(null);
          int i=0;
          while(r==JFileChooser.APPROVE_OPTION)
          {
          File f=selector.getSelectedFile();
          this.vectordeimagenes[i].setImage(ImageIO.read(new File(f.getPath())));
          i+=1;
          r=selector.showOpenDialog(null);                                        
          }
          
                                         
        
    }
    
    public double[] getHistograma(BufferedImage img)
    {
        double[] arreglo = new double[256];
        WritableRaster imgraster = img.getRaster();
        for (int i = 0; i < img.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < img.getHeight(); j = j + 1)
            {
                arreglo[imgraster.getSample(i, j, 0)]+=1;
            }
        }
        
        return arreglo;
        
    }
    
    public double[] histogramaNormalizado(double[] histograma,BufferedImage img)
            {
                double[] arreglonorm = new double[256];
                for (int i = 0; i < histograma.length ;i = i + 1)
                {
                    arreglonorm[i]=histograma[i]/(img.getWidth()*img.getHeight());
                }
                
                return arreglonorm;

                
            }
           

            
    
    public void showHistograma(Image img)
    {
        for (int i = 0; i <= 255 ;i = i + 1)
        {
            System.out.println("valor de gris "+ i + "cantidad" +img.getHistograma(img.bi)[i]);
        }
        
    }
    
     private int calcularUmbral(Image img) {
                int umbral=0;
                int L = 256; // numero de niveles de intensidad

        
                double minimo_umbral=Double.MAX_VALUE;
                double[] histograma=img.histogramaNormalizado(img.getHistograma(img.bi), img.bi);
                for (int T=0;T < L; T++){ //inicio bucle principal
                        double w1=0,w2=0;
                        //calculo probabilidades
                        for(int i=0;i<=T;i++){
                                w1=w1+histograma[i];
                        }
                        for(int j=T+1;j < L;j++){
                                w2=w2+histograma[j];
                        }
                        //calculo de las medias
                        double m1=0,m2=0;
                        for(int i=0;i<=T;i++){
                                m1=m1+((i*histograma[i])/w1);
                        }
                        for(int j=T+1;j < L;j++){
                                m2=m2+((j*histograma[j])/w2);
                        }
                        //calculo varianzas
                        double v1=0,v2=0;
                        for(int i=0;i<=T;i++){
                                v1=v1+Math.pow(i-m1,2)*((histograma[i])/w1);
                        }
                        for(int j=T+1;j < L;j++){
                                v2=v2+Math.pow(j-m2,2)*((histograma[j])/w2);
                        }
                        
                        double sg = w1*v1 + w2*v2;//varianza ponderada
                        
                        if (sg < minimo_umbral){
                                minimo_umbral=sg;
                                umbral=T;
                        }
                }//fin bucle principal
                return umbral;
                
        }

    public BufferedImage composicion(BufferedImage img1, BufferedImage img2) throws IOException
    {
        
        //this.setImageBack(this.Binarize(this.bi,this.calcularUmbral(this)));
        if(img1.getType()!=BufferedImage.TYPE_BYTE_GRAY)
        img1 = this.convertir(img1);
        if(img2.getType()!=BufferedImage.TYPE_BYTE_GRAY)
        img2 = this.convertir(img2);
        BufferedImage imagencompuesta = new BufferedImage(img1.getWidth(),img1.getHeight(),img1.getType());
        System.out.println("composicion type"+img1.getType()+img2.getType());
        BufferedImage imgescalada = this.zoomImage(img2, img1.getWidth(), img1.getHeight());
        this.setImageBack(imgescalada);
        BufferedImage mask = this.Binarize(this.bi,this.calcularUmbral(this));
        WritableRaster maskraster = mask.getRaster();
        WritableRaster imagescaladaraster = imgescalada.getRaster();
        WritableRaster img1raster = img1.getRaster();
        WritableRaster imagencompuestaraster = imagencompuesta.getRaster();
        
        for (int i = 0; i < img1.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < img1.getHeight(); j = j + 1)
            {
              if(maskraster.getSample(i, j, 0)==0)
              {
                  imagencompuestaraster.setSample(i, j, 0, img1raster.getSample(i, j, 0));
              }
              else if(maskraster.getSample(i, j, 0)==255)
              {
                  imagencompuestaraster.setSample(i, j, 0, imagescaladaraster.getSample(i, j, 0));
              }
            }
        }
        this.setImageBack(imagencompuesta);
        return imagencompuesta;
    }
    
    
     public BufferedImage composicionnormal(BufferedImage img1, BufferedImage img2, BufferedImage maska) throws IOException
    {
        
        //this.setImageBack(this.Binarize(this.bi,this.calcularUmbral(this)));
        if(img1.getType()!=BufferedImage.TYPE_BYTE_GRAY)
        img1 = this.convertir(img1);
        if(img2.getType()!=BufferedImage.TYPE_BYTE_GRAY)
        img2 = this.convertir(img2);
        BufferedImage imagencompuesta = new BufferedImage(img1.getWidth(),img1.getHeight(),img1.getType());
        System.out.println("composicion type"+img1.getType()+img2.getType());
        BufferedImage imgescalada = this.zoomImage(img2, img1.getWidth(), img1.getHeight());
        this.setImageBack(imgescalada);
        BufferedImage mask = this.zoomImage(maska, img1.getWidth(), img1.getHeight());
        WritableRaster maskraster = mask.getRaster();
        WritableRaster imagescaladaraster = imgescalada.getRaster();
        WritableRaster img1raster = img1.getRaster();
        WritableRaster imagencompuestaraster = imagencompuesta.getRaster();
        
        for (int i = 0; i < img1.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < img1.getHeight(); j = j + 1)
            {
              if(maskraster.getSample(i, j, 0)==255)
              {
                  imagencompuestaraster.setSample(i, j, 0, img1raster.getSample(i, j, 0));
              }
              else if(maskraster.getSample(i, j, 0)==0)
              {
                  imagencompuestaraster.setSample(i, j, 0, imagescaladaraster.getSample(i, j, 0));
              }
            }
        }
        this.setImageBack(imagencompuesta);
        return imagencompuesta;
    }
   
     
    public void setImageBack(String name) throws IOException
    {
        
            bi.flush();
            bi = ImageIO.read(new File(name));
            w = bi.getWidth();
            h = bi.getHeight();
            Graphics big = bi.getGraphics();
            big.drawImage(bi, 0, 0, null);
        //aca creaba una imagen y hacia un flush de la imagen y luego hacia lo mismo que se hace al inicio, sin embargo no me
        //estaba funcionando el filtro..
    }
    
    public void setImageBack(BufferedImage name) throws IOException
    {
        
            
            bi.flush();
            bi = name;
            
            
            w = bi.getWidth();
            h = bi.getHeight();
            Graphics big = bi.getGraphics();
            big.drawImage(bi, 0, 0, null);
        //aca creaba una imagen y hacia un flush de la imagen y luego hacia lo mismo que se hace al inicio, sin embargo no me
        //estaba funcionando el filtro..
    }

    
    public void setIntervalos(int r0,int r1,int r2,int g0,int g1,int g2,int b0,int b1,int b2)
    {
        this.intervalo[0]=(r0<<16)+(g0<<8)+b0;
        this.intervalo[1]=(r1<<16)+(g1<<8)+b1;
        this.intervalo[2]=(r2<<16)+(g2<<8)+b2;
        
    }
   
    
    public void aplicarFiltro(Float filtro[][],BufferedImage img) throws IOException
    {
        
        Float valor;
        
        System.out.println(filtro[1][2]);
        System.out.println(bi.getHeight());
        
        BufferedImage copia = this.makecopyImage(img);
                    
        WritableRaster raster = copia.getRaster();
        WritableRaster raster2 = img.getRaster();
        
            
        for (int i = 0; i < copia.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < copia.getHeight(); j = j + 1)
            {
                if( (i>0 && j>0) && (i+1 < bi.getWidth()) && (j+1 < bi.getHeight()))
                {
                    
                   
                    
                    valor= raster.getSample(i-1, j-1,0)*filtro[0][0]+
                            raster.getSample(i, j-1,0)*filtro[0][1]+
                            raster.getSample(i+1, j-1,0)*filtro[0][2]+
                            raster.getSample(i-1, j,0)*filtro[1][0]+
                            raster.getSample(i, j,0)*filtro[1][1]+
                            raster.getSample(i+1, j,0)*filtro[1][2]+
                            raster.getSample(i-1, j+1,0)*filtro[2][0]+
                            raster.getSample(i, j+1,0)*filtro[2][1]+
                            raster.getSample(i+1, j+1,0)*filtro[2][2];
        
                    if (valor < 0)
                        valor=0.0f;
                    
                    raster2.setSample(i, j, 0, valor.intValue());
                    
                }
            }
        }
        
        
     

        
            
    }
    
    @Override
    public void paint(Graphics g) {
        g.drawImage(bi, 0, 0, null);
    }
    
    
    public float calcularMedia(BufferedImage img)
    {
        float suma=0;
        int cantpixeles=0;
        WritableRaster rt = img.getRaster();
         for (int i = 0; i < img.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < img.getHeight(); j = j + 1)
            {
                suma+=rt.getSample(i, j,0);
                cantpixeles+=1;
            }
        }
         
         
         
         System.out.println("media"+ (int)(suma/cantpixeles) + "suma" + suma + "cant pixeles" + cantpixeles);
         return (int)(suma/cantpixeles);   
        
        
    }
    public BufferedImage aplicarContraste(BufferedImage img, int E)
    {
        
        WritableRaster rt = img.getRaster();
        
        BufferedImage ImagenContrastada = new BufferedImage(img.getWidth(),img.getHeight(),img.getType()); 
        WritableRaster rtcontrast = ImagenContrastada.getRaster();
        
        float media=0;
        int valor=0;
        media=this.calcularMedia(img);
        System.out.println("la media dentro de aplicar contraste es "+ media);
         for (int i = 0; i < img.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < img.getHeight(); j = j + 1)
            {
                
                valor = (int) (255*(1/(1+(Math.pow(media/rt.getSample(i, j,0),E)))));
                rtcontrast.setSample(i, j, 0, valor);
                
            }
        }
        
         return ImagenContrastada;
        
        
    }

    
    //resalta sangre (5,100,200.10,10,160.60,20,255)
    public BufferedImage acolor()
    {
        
        
        int pixelgris;
        int width = bi.getWidth(); // Dimensions of the image
        int height = bi.getHeight();
        
        int red;
        int green;
        int blue;
        
        int rednew;
        int greennew;
        int bluenew;
        
        
        //LUEGO DEBERAN SER PASADOS COMO PARAMETROS LOS INTERVALOS
        double r0 = (intervalo[0] >> 16)& 255;
        double r1 = (intervalo[1] >> 16)& 255;
        double r2 = (intervalo[2] >> 16)& 255;
                   System.out.println("ere cero "+r1);
                        
        double gr0 = (intervalo[0] >> 8)& 255;
        double gr1 = (intervalo[1] >> 8)& 255;
        double gr2 = (intervalo[2] >> 8)& 255;
                   System.out.println("ge cero "+gr1);
                        
        double b0 = (intervalo[0])& 255;
        double b1 = (intervalo[1])& 255;
        double b2 = (intervalo[2])& 255;
                   System.out.println("azul cero "+b1);
                        
        int g0;

        
        // Let's create a BufferedImage for a gray level image.
        colorimage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
      
        for (int i = 0; i < bi.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < bi.getHeight(); j = j + 1)
            {
                pixelgris = this.bi.getRaster().getSample(i, j, 0);
                        
                    if (pixelgris <= 128)
                    {
                        red = (int) (r0 + (((r1-r0)/128) * pixelgris));
                        green= (int) (gr0 + (((gr1-gr0)/128) * pixelgris));
                        blue =(int) (b0 + (((b1-b0)/128) * pixelgris));
              
             
                        rednew = (red << 16);
                        greennew = (green << 8);
                        bluenew = blue;

                     

                        colorimage.setRGB(i, j, rednew+greennew+bluenew);
                    }
                    else
                    {
                        g0=128;
                        red = (int) (r0 + (((r1-r0)/128) * (pixelgris-128)));
                        green= (int) (gr0 + (((gr1-gr0)/128) * (pixelgris-128)));
                        blue =(int) (b0 + (((b1-b0)/128) * (pixelgris-128)));
                        
                        rednew = (red << 16);
                        greennew = (green << 8);
                        bluenew = blue;
                        
                        colorimage.setRGB(i, j, rednew+greennew+bluenew);
                    }
             }
        }
        
       
        
        return colorimage;
     }
        
        
    
  
    
    public BufferedImage convertir() throws IOException
    {
        
        BufferedImage im = new BufferedImage(bi.getWidth(),bi.getHeight(),BufferedImage.TYPE_BYTE_GRAY);
        
        WritableRaster rt = im.getRaster();
        for(int i=0; i<bi.getWidth(); i++){
            for(int j=0; j<bi.getHeight(); j++){
                int color = bi.getRGB(i,j);

                int alpha = (color >> 24) & 255;
                int red = (color >> 16) & 255;
                int green = (color >> 8) & 255;
                int blue = (color) & 255;

                final int lum = (int)(0.2126 * red + 0.7152 * green + 0.0722 * blue);
               // final int lum = (int)(0.166 * red + 0.666 * green + 0.166 * blue);

                
                alpha = (alpha << 24);
                red = (lum << 16);
                green = (lum << 8);
                blue = lum;

                color = alpha + red + green + blue;

                rt.setSample(i,j,0,color);
            }
        }
        return im;
    }
        
        
    public BufferedImage convertir(BufferedImage bi) throws IOException
    {
        
        BufferedImage im = new BufferedImage(bi.getWidth(),bi.getHeight(),BufferedImage.TYPE_BYTE_GRAY);
        
        WritableRaster rt = im.getRaster();
        for(int i=0; i<bi.getWidth(); i++){
            for(int j=0; j<bi.getHeight(); j++){
                int color = bi.getRGB(i,j);

                int alpha = (color >> 24) & 255;
                int red = (color >> 16) & 255;
                int green = (color >> 8) & 255;
                int blue = (color) & 255;

                final int lum = (int)(0.2126 * red + 0.7152 * green + 0.0722 * blue);
               // final int lum = (int)(0.166 * red + 0.666 * green + 0.166 * blue);

                
                alpha = (alpha << 24);
                red = (lum << 16);
                green = (lum << 8);
                blue = lum;

                color = alpha + red + green + blue;

                rt.setSample(i,j,0,color);
            }
        }
        
        System.out.println("ahora es" + bi.getType());
    
        return im;
    }
    
    public void showInformation()
    {
        System.out.println("altura" +bi.getHeight());
        System.out.println("ancho" +bi.getWidth());
        System.out.println(bi.getColorModel());
        System.out.println("Transparencia" +bi.getTransparency());
        System.out.println("Tipo" +bi.getType());
    }
    
    public BufferedImage SumarImagenes(BufferedImage im1, BufferedImage im2)
    {
        if (im1.getWidth() > im2.getWidth())
        {
            if(im1.getHeight() > im2.getHeight())
            {
                //aca se suma la imagen 2 a la 1
            }
            
            //aca la imagen 2 es mas alta pero la 1 mas ancha, se construye una nueva de alto de imagen 2 y ancho de 1
        }
        else if(im1.getWidth() <= im2.getWidth())
        {
            if(im1.getHeight() < im2.getHeight())
            {
                //se suma la imagen 1 a la 2
            }
            //aca se construye una de ancho imagen 2 u alto imagen 1
        }
        return im1;
    }
    
    
    public void negative()
    {
        System.out.println("negativo");
        if (this.type == BufferedImage.TYPE_INT_RGB)
        {
        for (int i = 0; i < bi.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < bi.getHeight(); j = j + 1)
            {
                this.bi.setRGB(i, j, 0xffffff - bi.getRGB(i, j));
            }
        }
            
        }
        if (this.type == BufferedImage.TYPE_BYTE_GRAY)
        {
            WritableRaster raster = this.bi.getRaster();
            for (int i = 0; i < bi.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < bi.getHeight(); j = j + 1)
            {
                raster.setSample(i, j, 0, 255 - bi.getRaster().getSample(i, j, 0));
            }
        }
        
        
         System.out.print(this.bi.getRGB(10, 10));
        }
        System.out.println("es del tipo" + this.type );
        
    }
    
    
    // 0xabcdef a:alphared b:red c:alphagreen d:green e:alphablue f:blue
    public void Binarize()
    {
        
             
            
                System.out.println("afuera" + this.bi.getType() + BufferedImage.TYPE_BYTE_GRAY);
        if (this.bi.getType() == BufferedImage.TYPE_BYTE_GRAY)
        {
            System.out.println("entre");
            WritableRaster raster = this.bi.getRaster();
            for (int i = 0; i < bi.getWidth(); i = i + 1)
            {
                for (int j=0 ; j < bi.getHeight(); j = j + 1)
                {
                    if (raster.getSample(i, j, 0) < 180)
                    {
                    raster.setSample(i, j, 0, 0);
                    }
                    else
                        raster.setSample(i, j, 0, 255);


                }
            }
         }
        
           if (this.bi.getType()==BufferedImage.TYPE_INT_RGB)
                 {
                    for (int i = 0; i < bi.getWidth(); i = i + 1)
                    {
                        for (int j=0 ; j < bi.getHeight(); j = j + 1)
                        {
                            if (this.bi.getRGB(i, j) < -0xbfbfbf)
                            this.bi.setRGB(i, j, -0xffffff);
                            else
                            this.bi.setRGB(i, j, 0xffffff);

                        }
                    }
                }

        
       
        
        
    }
    
    
    public BufferedImage Binarize(BufferedImage imge)
    {
        
             
        BufferedImage img = new BufferedImage(imge.getWidth(),imge.getHeight(),imge.getType());
        WritableRaster raster = img.getRaster();
        WritableRaster rasterorg = imge.getRaster();
            for (int i = 0; i < img.getWidth(); i = i + 1)
            {
                for (int j=0 ; j < img.getHeight(); j = j + 1)
                {
                    if (rasterorg.getSample(i, j, 0) < 140)
                    {
                    raster.setSample(i, j, 0, 0);
                    }
                    else
                        raster.setSample(i, j, 0, 255);


                }
            }
         
        
       return img;
    }
    
    
    public BufferedImage Binarize(BufferedImage imge, int umbral)
    {
        
             
        BufferedImage img1 = new BufferedImage(imge.getWidth(),imge.getHeight(),imge.getType());
        WritableRaster raster = img1.getRaster();
        WritableRaster rasterorg = imge.getRaster();
            for (int i = 0; i < img1.getWidth(); i = i + 1)
            {
                for (int j=0 ; j < img1.getHeight(); j = j + 1)
                {
                    if (rasterorg.getSample(i, j, 0) < umbral)
                    {
                    raster.setSample(i, j, 0, 0);
                    }
                    else
                        raster.setSample(i, j, 0, 255);


                }
            }
         
        
       return img1;
    }
    
    public int[][] getPixels()
    {
        int [][] iterator = null;
            for (int i = 0; i < bi.getHeight(); i = i + 1)
        {
            for (int j=0 ; j < bi.getWidth(); j = j + 1)
            {
                iterator[j][i]=bi.getRGB(j, i);
            }
        }
            return iterator;
    }
    
    

    public Dimension getPreferredSize() {
        return new Dimension(w, h);
    }

    
   

    
    /* Return the formats sorted alphabetically and in lower case */
    public String[] getFormats() {
        String[] formats = ImageIO.getWriterFormatNames();
        TreeSet<String> formatSet = new TreeSet<String>();
        for (String s : formats) {
            formatSet.add(s.toLowerCase());
        }
        return formatSet.toArray(new String[0]);
    }
    
    public BufferedImage zoomImage(BufferedImage im, float factor) throws IOException
    {
        int wi = im.getWidth();
        int wh = im.getHeight();
        BufferedImage zoomed = new BufferedImage((int)(wi*factor),(int)(wh*factor),im.getType());
        for (int i = 0; i < zoomed.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < zoomed.getHeight(); j = j + 1)
            {
                zoomed.setRGB(i, j, im.getRGB((int)(Math.floor(i)/factor),(int)(Math.floor(j)/factor)));
                   
            }
            System.out.println((int)(Math.floor(i)/factor));
            
        }
      //  ImageIO.write(zoomed,"PNG",new File("C:/Users/rodrigo/Desktop/glpattern.png"));
        return zoomed;
        
    }

      public BufferedImage zoomImage(BufferedImage im, float width, float height) throws IOException
    {
        int wi = im.getWidth();
        int wh = im.getHeight();
        float factorw;
        float factorh;
        
        factorw=width/wi;
        factorh=height/wh;
        System.out.println("factor" + (factorh));
        
        BufferedImage zoomed = new BufferedImage((int)(width),(int)(height),im.getType());
        for (int i = 0; i < zoomed.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < zoomed.getHeight(); j = j + 1)
            {
                zoomed.setRGB(i, j, im.getRGB((int)(Math.floor(i)/factorw),(int)(Math.floor(j)/factorh)));
                   
            }
            
            
        }
      //  ImageIO.write(zoomed,"PNG",new File("C:/Users/rodrigo/Desktop/glpattern.png"));
        return zoomed;
        
    }
      
      public BufferedImage RegistrarImagenesaColor(BufferedImage img1, BufferedImage img2) throws IOException
      {
          BufferedImage imagenregistrada = new BufferedImage(img1.getWidth(),img1.getHeight(),img1.getType());
          BufferedImage imgescalada = this.zoomImage(img2, img1.getWidth(), img1.getHeight());
                
                if(this.img.getPuntosdeControl().isEmpty()==false&&this.img2.getPuntosdeControl().isEmpty()==false&&this.img.getPuntosdeControl().size()==this.img2.getPuntosdeControl().size())
                {
                    
                            int ideimg2=0;
                            int jdeimg2=0;
                            int diferenciax=Integer.parseInt(this.img2.getPuntosdeControl().get(0).toString())-Integer.parseInt(this.img.getPuntosdeControl().get(0).toString());
                            int diferenciay=Integer.parseInt(this.img2.getPuntosdeControl().get(1).toString())-Integer.parseInt(this.img.getPuntosdeControl().get(1).toString());
                            ideimg2=diferenciay;
                            jdeimg2=diferenciax;
                            
                            System.out.println("diferencias "+jdeimg2+","+ideimg2);
                            for (int i = 0; i < imagenregistrada.getHeight(); i = i + 1)
                                {
                                    
                                jdeimg2=diferenciax;
                                for (int j=0 ; j < imagenregistrada.getWidth(); j = j + 1)
                                {
                                       if(jdeimg2>0 && jdeimg2<imgescalada.getWidth() && ideimg2>0 && ideimg2<imgescalada.getHeight())
                                       {
                                       imagenregistrada.setRGB(j, i, Math.round((img1.getRGB(j, i)+imgescalada.getRGB(jdeimg2,ideimg2))/2));
                                    
                                       }
                                       else
                                       {
                                           imagenregistrada.setRGB(j, i,img1.getRGB(j, i));
                                       }
                                       jdeimg2+=1;       
                                }
                                ideimg2+=1;
                            
                            }
                }
                else
                {
                    System.out.println("No hay puntos de control o bien no existen la misma cantidad de puntos de control en ambas imágenes "+this.img.getPuntosdeControl().get(0));
                }
                return imagenregistrada;

      }
          
      
    
      public BufferedImage RegistrarImagenes(BufferedImage img1, BufferedImage img2) throws IOException
      {
        
                if(img1.getType()!=BufferedImage.TYPE_BYTE_GRAY)
                img1 = this.convertir(img1);
                if(img2.getType()!=BufferedImage.TYPE_BYTE_GRAY)
                img2 = this.convertir(img2);
                
                BufferedImage imagenregistrada = new BufferedImage(img1.getWidth(),img1.getHeight(),img1.getType());
                BufferedImage imgescalada = this.zoomImage(img2, img1.getWidth(), img1.getHeight());
                WritableRaster imagescaladaraster = imgescalada.getRaster();
                WritableRaster img1raster = img1.getRaster();
                WritableRaster imagenregistradaraster = imagenregistrada.getRaster();

                System.out.println("imgf" + imagenregistrada.getWidth() + "imgf" + imagenregistrada.getHeight());
                System.out.println("img1widt" + img1raster.getWidth() + "img2widt" + imagescaladaraster.getWidth());
                System.out.println("img1hidt" + img1raster.getHeight() + "img2hidt" + imagescaladaraster.getHeight());
                
                if(this.img.getPuntosdeControl().isEmpty()==false&&this.img2.getPuntosdeControl().isEmpty()==false&&this.img.getPuntosdeControl().size()==this.img2.getPuntosdeControl().size())
                {
                    
                            int ideimg2=0;
                            int jdeimg2=0;
                            int diferenciax=Integer.parseInt(this.img2.getPuntosdeControl().get(0).toString())-Integer.parseInt(this.img.getPuntosdeControl().get(0).toString());
                            int diferenciay=Integer.parseInt(this.img2.getPuntosdeControl().get(1).toString())-Integer.parseInt(this.img.getPuntosdeControl().get(1).toString());
                            ideimg2=diferenciay;
                            jdeimg2=diferenciax;
                            
                            System.out.println("diferencias "+jdeimg2+","+ideimg2);
                            for (int i = 0; i < imagenregistradaraster.getHeight(); i = i + 1)
                                {
                                    
                                jdeimg2=diferenciax;
                                for (int j=0 ; j < imagenregistradaraster.getWidth(); j = j + 1)
                                {
                                       if(jdeimg2>0 && jdeimg2<imgescalada.getWidth() && ideimg2>0 && ideimg2<imgescalada.getHeight())
                                       {
                                       imagenregistradaraster.setSample(j, i, 0, Math.round((img1raster.getSample(j, i, 0)+imagescaladaraster.getSample(jdeimg2,ideimg2,0))/2));
                                    
                                       }
                                       else
                                       {
                                           imagenregistradaraster.setSample(j, i, 0,img1raster.getSample(j, i, 0));
                                       }
                                       jdeimg2+=1;       
                                }
                                ideimg2+=1;
                            
                            }
                }
                else
                {
                    System.out.println("No hay puntos de control o bien no existen la misma cantidad de puntos de control en ambas imágenes ");
                }
                return imagenregistrada;

      }
          
          
      


     public void actionPerformed(ActionEvent e) {
         
         System.out.println( e.getActionCommand());
         if(e.getActionCommand()=="Gris-Color")
         {
             this.setIntervalos(Integer.parseInt(this.r0.getText()),Integer.parseInt(this.r1.getText()),
                     Integer.parseInt(this.r2.getText()), Integer.parseInt(this.g0.getText()),
                     Integer.parseInt(this.g1.getText()),Integer.parseInt(this.g2.getText()),
                     Integer.parseInt(this.b0.getText()),Integer.parseInt(this.b1.getText()),
                     Integer.parseInt(this.b2.getText()));
            try {
                this.setImageBack(this.acolor());
               // minuevoejemplo.setImage(this.acolor());
               // minuevoejemplo.setImage(this.acolor());
            } catch (IOException ex) {
                Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
            }
                
               
        }     
        if(e.getActionCommand()=="Filtro")
         {
             Float matriz[][] = new Float[3][3];
             matriz[0][0]=Float.parseFloat(this.f0.getText());
             matriz[0][1]=Float.parseFloat(this.f1.getText());
             matriz[0][2]=Float.parseFloat(this.f2.getText());
             matriz[1][0]=Float.parseFloat(this.f3.getText());
             matriz[1][1]=Float.parseFloat(this.f4.getText());
             matriz[1][2]=Float.parseFloat(this.f5.getText());
             matriz[2][0]=Float.parseFloat(this.f6.getText());
             matriz[2][1]=Float.parseFloat(this.f7.getText());
             matriz[2][2]=Float.parseFloat(this.f8.getText());
            try {
                this.aplicarFiltro(matriz,this.bi);
            } catch (IOException ex) {
                Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
            }
             
             
                
               
        }     
        
        if(e.getActionCommand()=="Cargar Imágen")
        {
                                

                                     JFileChooser selector=new JFileChooser();
                                     FileNameExtensionFilter filtroImagen=new FileNameExtensionFilter("JPG, PNG & GIF","jpg","png","gif");
                                        selector.setFileFilter(filtroImagen);
                                        int r=selector.showOpenDialog(null);
                                        if(r==JFileChooser.APPROVE_OPTION){
                                         try {
                                                  File f=selector.getSelectedFile();
                                                  
                                                  this.setImageBack(f.getPath());
                                                  
                                                   } catch (IOException ex) {
                                                        Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
                                                  
                                                }
                                        }
        
         } 
                                
                
                
                
            
        
        
        if(e.getActionCommand()=="Escalar")
         try {
            
            this.setImageBack(this.zoomImage(bi, Float.parseFloat(this.z0.getText()),Float.parseFloat(this.z1.getText())));
          //  BufferedImage im = this.zoomImage(bi, 3);
          //  NewImage minuevoejemplo = new NewImage(im);
           // minuevoejemplo.setImage(this.zoomImage(bi, 3));
           // minuevoejemplo.setImage(this.zoomImage(bi, 3));
            System.out.println("despues"+bi.getWidth());
        } catch (IOException ex) {
            Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
        }
         
        if("Aplicar Contraste".equals(e.getActionCommand()))
        {
            try {
                this.setImageBack(this.aplicarContraste(bi, Integer.parseInt(JOptionPane.showInputDialog(null, "INGRESE Factor de contraste"))));
            } catch (IOException ex) {
                Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        if("Binarizar".equals(e.getActionCommand()))
        {
            System.out.println("antes"+bi.getType());
            try {
                this.setImageBack(this.Binarize(this.bi,this.calcularUmbral(this)));
            } catch (IOException ex) {
                Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
         if("Color-gris".equals(e.getActionCommand()))
         try {
            this.setImageBack(this.convertir());
        } catch (IOException ex) {
            Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
        }
         
         if ("prewitt".equalsIgnoreCase(e.getActionCommand()))
                 {
            try {
                Float matriz1[][] = new Float[3][3];
                matriz1[0][0]=-1f;
                matriz1[0][1]=-1f;
                matriz1[0][2]=-1f;
                matriz1[1][0]=0f;
                matriz1[1][1]=0f;
                matriz1[1][2]=0f;
                matriz1[2][0]=1f;
                matriz1[2][1]=1f;
                matriz1[2][2]=1f;
                Float matriz2[][] = new Float[3][3];
                matriz2[0][0]=-1f;
                matriz2[0][1]=0f;
                matriz2[0][2]=1f;
                matriz2[1][0]=-1f;
                matriz2[1][1]=0f;
                matriz2[1][2]=1f;
                matriz2[2][0]=-1f;
                matriz2[2][1]=0f;
                matriz2[2][2]=1f;
                this.aplicarFiltro(matriz1, this.bi);
                this.aplicarFiltro(matriz2, this.bi);
            } catch (IOException ex) {
                Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
            }
             
                     
                 }
         
         
         
         if (e.getActionCommand()=="RegistrarImagenes")         
         {
             if(this.img.getType()=="registro"&&this.img2.getType()=="registro")
             {
                    try {
                        BufferedImage imgregistrada = this.RegistrarImagenes(this.img.getImage(), this.img2.getImage());
                        this.setImageBack(imgregistrada);
                        this.img.setImage(imgregistrada);
                    } catch (IOException ex) {
                        Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
                    }
             }
         }
         
         if(e.getActionCommand()=="cargar_imagenes_registrar_madre")
         {
                                      JFileChooser selector=new JFileChooser();
                                   //   JFileChooser selector2=new JFileChooser();
          
                                       FileNameExtensionFilter filtroImagen=new FileNameExtensionFilter("JPG, PNG & GIF","jpg","png","gif");
                                       
                                        selector.setFileFilter(filtroImagen);
                                     //   selector2.setFileFilter(filtroImagen);
                                        
                                        int r=selector.showOpenDialog(null);
                                      //  int r2=selector2.showOpenDialog(null);
                                        
                                        if(r==JFileChooser.APPROVE_OPTION){
                                         try {
                                                  File f=selector.getSelectedFile();  
                                        //          File f2=selector2.getSelectedFile();                                              
                                              
                                                  this.img.setImage(ImageIO.read(new File(f.getPath())));
                                        //          this.img2.setImage(ImageIO.read(new File(f2.getPath())));
                                                  
                                                   } catch (IOException ex) {
                                                        Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
                                                  
                                                }
                                        }
            try {
                this.setImageBack(this.img.getImage());
            } catch (IOException ex) {
                Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
            }
           
         }
         
         
         if(e.getActionCommand()=="cargar_imagenes_registrar_hijas")
         {
                                      JFileChooser selector=new JFileChooser();
                                   //   JFileChooser selector2=new JFileChooser();
          
                                       FileNameExtensionFilter filtroImagen=new FileNameExtensionFilter("JPG, PNG & GIF","jpg","png","gif");
                                       
                                        selector.setFileFilter(filtroImagen);
                                     //   selector2.setFileFilter(filtroImagen);
                                        
                                        int r=selector.showOpenDialog(null);
                                      //  int r2=selector2.showOpenDialog(null);
                                        
                                        if(r==JFileChooser.APPROVE_OPTION){
                                         try {
                                                  File f=selector.getSelectedFile();  
                                        //          File f2=selector2.getSelectedFile();                                              
                                              
                                                  this.img2.setImage(ImageIO.read(new File(f.getPath())));
                                        //          this.img2.setImage(ImageIO.read(new File(f2.getPath())));
                                                  
                                                   } catch (IOException ex) {
                                                        Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
                                                  
                                                }
                                        }
           
         }
         if(e.getActionCommand()=="componer")
         {
             
             if(this.img.getType()=="componer"&&this.img2.getType()=="componer")
             {
                         try {
                        if(this.img2.isSet)//si se ha guardado
                        {
                        this.img2.setImage(this.img2.getBackImage());
                        this.img2.isSet=false;
                        }
                        this.composicionnormal(img.getImage(), img2.getImage(),img2.getMask());
                    } catch (IOException ex) {
                        Logger.getLogger(Image.class.getName()).log(Level.SEVERE, null, ex);
                    }
             }
             
         }
         
         if("Componer_por_otsu".equalsIgnoreCase(e.getActionCommand()))
         {
                
                try{
                                           JFileChooser selector=new JFileChooser();
                                           FileNameExtensionFilter filtroImagen=new FileNameExtensionFilter("JPG, PNG & GIF","jpg","png","gif");
                                           selector.setFileFilter(filtroImagen);
                                           JFileChooser selector2=new JFileChooser();
                                           selector2.setFileFilter(filtroImagen);
                                           int r12=selector2.showOpenDialog(null);
                                           int r=selector.showOpenDialog(null);
                                           if((r==JFileChooser.APPROVE_OPTION) && (r12==JFileChooser.APPROVE_OPTION)){
                                           
                                                     File f11=selector.getSelectedFile();
                                                     BufferedImage imagen1=ImageIO.read(new File(f11.getPath()));
                                                     File f12=selector2.getSelectedFile();
                                                     BufferedImage imagen2=ImageIO.read(new File(f12.getPath()));
                                                     if(imagen1.getType()==BufferedImage.TYPE_INT_RGB)
                                                     {
                                                         this.convertir(imagen1);
                                                     }
                                                     if(imagen2.getType()==BufferedImage.TYPE_INT_RGB)
                                                     {
                                                         this.convertir(imagen2);
                                                     }
                                                     this.setImageBack(this.composicion(imagen1, imagen2));
                                          }
                                           
                                           
                                           
                }catch(IOException ex)
                {
                    System.out.println("error de IO" + ex.getStackTrace());
                }
                
             
         }
         
         if(e.getActionCommand()=="Cargar Puntos Control")
         {
             this.img.setType("registro");
             this.img2.setType("registro");
             
         }
         
          if(e.getActionCommand()=="Generar Mascara Composicion")
         {
             if(this.img2.isSet==false)//si no ha sido guardada antes
             {
             this.img2.saveImage();
             this.img2.isSet=true;
             }
             this.img2.setMask(this.img2.getImage());
             this.img.setType("componer");
             this.img2.setType("componer");
             
         }
         
         
         repaint();
         
         
    };
     
     
    public static void main(String[] args) throws IOException {

        
        
      //  FlowLayout experimentLayout = new FlowLayout();
        GridLayout LFiltros = new GridLayout(0,3);
        GridLayout LInterv = new GridLayout(0,3);
        GridLayout LPGFiltros = new GridLayout(0,1);
        GridLayout imgPanelLayout = new GridLayout(0,2);
        
       
        
        
        JFrame f = new JFrame("Principal");
        //agrege
        JPanel ci = new JPanel();
        //agrege
        JFrame frame = new JFrame("Display image");
        JPanel pf = new JPanel(); //panel filtros
        JPanel pz = new JPanel(); //panel de zooming
        JPanel pc = new JPanel(); //panel intervalos gris-color
        JPanel pgf = new JPanel(); //panel general de filtros
        JPanel pb = new JPanel(); //panel general de BOTONES
        JPanel lblpf = new JPanel(); //label filtros
        JPanel lblpc = new JPanel(); //label pc
        JPanel lblzo = new JPanel(); //lbl zoom
        JPanel imgPanel = new JPanel(); //lbl zoom
        
        
        
        
        
        
       // f.setLayout(experimentLayout);
        //agrege
        
        frame.setLayout(new GridLayout(2,2));
        ci.setLayout(new BorderLayout());
        imgPanel.setLayout(imgPanelLayout);
        
        pf.setLayout(LFiltros);
        pc.setLayout(LInterv);
        pb.setLayout(LPGFiltros);
        pz.setLayout(LInterv);
        pgf.setLayout(LPGFiltros);
        lblpf.setLayout(LPGFiltros);
        lblpc.setLayout(LPGFiltros);
        
        
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        Image si = new Image();
        
       si.calcularUmbral(si);

        //agregue
       
        si.img.addMouseListener(si.img);
        si.img2.addMouseListener(si.img2);
        si.img2.addMouseMotionListener(si.img2);
  
        si.b.addActionListener(si);
        si.c.addActionListener(si);
        si.to.addActionListener(si);
        si.f.addActionListener(si);
        si.ci.addActionListener(si);
        si.zo.addActionListener(si);
        si.ctrt.addActionListener(si);
        si.comp.addActionListener(si);
        si.compo.addActionListener(si);
        si.prewitt.addActionListener(si);
        //agrege
        si.pc.addActionListener(si);
        si.pch.addActionListener(si); 
        si.ri.addActionListener(si);
        si.gmc.addActionListener(si);
        si.gpc.addActionListener(si);
          
             
       //agregue
        imgPanel.add(si.img);
        imgPanel.add(si.img2);
        ci.add(si,BorderLayout.CENTER);
        ci.add(imgPanel,BorderLayout.SOUTH);
        f.add(ci,BorderLayout.CENTER);
        
     
        pb.add(si.b); //gris-color boton
        pb.add(si.c); //binarizar
        pb.add(si.to); //color-gris
        pb.add(si.f); //aplicar filtro
        pb.add(si.ci);//cargar imágen
        pb.add(si.zo);//hacer zoom
        pb.add(si.ctrt);//aplicar contraste
        pb.add(si.comp);//composicion de dos imagenes que se piden al usuario, la primera es sobre la que se compone, mediante otsu
        pb.add(si.prewitt); //filtro bordes prewitt
        pb.add(si.pc); //registracion de imágenes, muestra los puntos de control por pantalla, imagen madre
        pb.add(si.pch); //imagen hija 
        pb.add(si.ri);//registra las dos imagenes
        pb.add(si.compo);//composicion en la que el usuario genera la mascara
        pb.add(si.gmc);//habilita los puntos de control y pone a las imagenes como tipo para registrar
        pb.add(si.gpc);//habilita la generacion de la mascara para la composicion por parte del usuario en la imagen 2, tambien pone el tipo de las
                        //imagenes img e img2 en componer
        
        f.add(pb,BorderLayout.EAST); //agrego panel de borones al este (derecha)
        
        pc.add(si.r0);
        pc.add(si.r1);
        pc.add(si.r2);
        pc.add(si.g0);
        pc.add(si.g1);
        pc.add(si.g2);
        pc.add(si.b0);
        pc.add(si.b1);
        pc.add(si.b2);
       
        
        pf.add(si.f0);
        pf.add(si.f1);
        pf.add(si.f2);
        pf.add(si.f3);
        pf.add(si.f4);
        pf.add(si.f5);
        pf.add(si.f6);
        pf.add(si.f7);
        pf.add(si.f8);
        
        pz.add(si.z0);
        pz.add(si.z1);
       
        lblpf.add(si.lblFiltros);
        lblpf.add(pf);
        
        lblpc.add(si.lblIntervalos);
        lblpc.add(pc);
        
        
        lblzo.add(si.lblZoom);
        lblzo.add(pz);
        
        pgf.add(lblpf);
        pgf.add(lblpc);
        pgf.add(lblzo);
   
        f.add(pgf,BorderLayout.WEST);
        
        f.pack();
        
        f.setVisible(true);
       
        
        
    }
    
    public BufferedImage makecopyImage(BufferedImage img) throws IOException
    {
       // Let's create a BufferedImage for a gray level image.
       BufferedImage copy = new BufferedImage(img.getWidth(),img.getHeight(),img.getType());
       WritableRaster raster = copy.getRaster();
       WritableRaster raster2 = img.getRaster();
       
       for (int i = 0; i < copy.getWidth(); i = i + 1)
        {
            for (int j=0 ; j < copy.getHeight(); j = j + 1)
            {
               raster.setSample(i, j, 0, raster2.getSample(i, j, 0)); 
            }
            
        }
       return copy;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println(e.getX() + e.getY());
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }


   
}




/*
    public static final float[] BLUR3x3 = {
        0.1f, 0.1f, 0.1f,    // low-pass filter kernel
        0.1f, 0.2f, 0.1f,
        0.1f, 0.1f, 0.1f
    };
     * 
     */

/*
 * public void makegreyImage() throws IOException
    {
    int width = 512; // Dimensions of the image
       int height = 512;
       // Let's create a BufferedImage for a gray level image.
       BufferedImage im = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
       // We need its raster to set the pixels' values.
       WritableRaster raster = im.getRaster();
       // Put the pixels on the raster, using values between 0 and 255.
       for(int h=0;h<height;h++)
         for(int w=0;w<width;w++)
           {
           int value = 127+(int)(128*Math.sin(w/32.)*Math.sin(h/32.)); // Weird sin pattern.
           raster.setSample(w,h,0,value); 
           }
       // Store the image using the PNG format.
       ImageIO.write(im,"PNG",new File("C:/Users/rodrigo/Desktop/glpattern.png"));
    }
    
 */